#!/bin/bash

# Wildcard-plugin to monitor traffic and errors on network
# interfaces. To monitor an interface, link if_<interface> to this
# file. E.g.

#    ln -s /usr/share/node/node/plugins-auto/if_ /etc/munin/node.d/if_eth0

# ...will monitor eth0.

# Any device found in /proc/net/dev can be monitored. Examples include
# ipsec*, eth*, irda* and lo. Please note that aliases cannot be
# monitored with this plugin.

# Magic markers (optional - used by munin-config and some installation
# scripts):

#%# family=auto
#%# capabilities=autoconf suggest

. $MUNIN_LIBDIR/plugins/plugin.sh

INTERFACE=${0##*if_}

findspeed () {

    # Who whould have thought it's so much work to determine the
    # maximum speed of a network interface.  Buckle up!

    IWLIST="$(type -p iwlist)"

    WIRELESS=0
    # Do not use interface name to guess technology.  Many many
    # wifi drivers use "eth*" names.
    case $IWLIST in

	'')
            # Used to use iwconfig to look for "no wireless
            # extentions" message - but this seemed un-needed.  If we
            # don't have iwlist we can't find out if # the interface
            # is wireless
            :;;
	*)  IWO="$($IWLIST $INTERFACE rate 2>&1)"
            case $IWO in
                *no*) :;;
	        *) WIRELESS=1;;
	    esac
	    ;;
    esac

    SPEED=U
    # Find speed in Mbps. - or not
    case $WIRELESS:$IWLIST in
	0:*)
	    ETHTOOL="$(type -p ethtool)"
	    if [ -x "$ETHTOOL" ]; then
		SPEED="$($ETHTOOL $INTERFACE |
                         awk '/Speed:/ { gsub(/[^0-9]*/,"",$2); print $2; }')"
		case $SPEED in
		    [0-9]*) :;; # OK
		    *)      SPEED=U;; # Could be "unknown"
		esac
	    else
		INSTALL="ethtool"
	    fi
	    ;;
	1:/*)
	    # Current bit rate is not very interesting, it varies too often
	    SPEED=$(echo "$IWO" |
		    awk 'BEGIN { RATE=U }
                               { if ($2 == "Mb/s") RATE=$1; } 
                         END   { print RATE; }')

	    ;;
	*)
	    # Wireless interface, cannot find iwlist
	    INSTALL="wireless-tools"
	    ;;
    esac

    MIITOOL="$(type -p mii-tool)"
    case $SPEED:$MIITOOL in
	U:/*)
	    SPEED="$($MIITOOL $INTERFACE 2>&1)"
	    case $SPEED in
		*1000base*) SPEED=1000;; # as if...
		*100base*)  SPEED=100;;
		*10base*)   SPEED=10;;
		*)          SPEED=U;;
	    esac
	    ;;
    esac

    case $SPEED in
	U) echo "up.info Traffic of the $INTERFACE interface. Unable to determine interface speed.  Please install ethtool, wireless-tools (or mii-tool), whatever is apropriate for the interface."
	   return;;
    esac

    BPS=$(( $SPEED * 1000 * 1000 ))

    cat <<EOF
up.max $BPS
up.info Traffic of the $INTERFACE interface. Maximum speed is $SPEED Mbps.
down.max $BPS
EOF

    return
}


case $1 in
    autoconf)
	if [ -r /proc/net/dev ]; then
	    echo yes
	    exit 0
	else
	    echo "no (/proc/net/dev not found)"
	    exit 1
	fi
	;;
    suggest)
	if [ -r /proc/net/dev ]; then
	    awk '
                /^ *(eth|tap|bond|wlan|ath|ra|sw)[0-9]+:/ {
                   split($0, a, /: */);
                   gsub(/^ +/,"",a[1]);
                   if (($2 > 0) || ($10 > 0)) print a[1]; }' /proc/net/dev

# 	    egrep '^ *(eth|tap|bond|wlan|ath|ra|sw)[0-9]+:' /proc/net/dev | cut -f1 -d: | sed 's/ //g'
	fi
	exit 0
	;;
    config)
		       
	echo "graph_order down up" 
	echo "graph_title $INTERFACE traffic"
	echo 'graph_args --base 1000'
	echo 'graph_vlabel bits in (-) / out (+) per ${graph_period}'
	echo 'graph_category network'
	echo "graph_info This graph shows the traffic of the $INTERFACE network interface. Please note that the traffic is shown in bits per second, not bytes. IMPORTANT: On 32 bit systems the data source for this plugin uses 32bit counters, which makes the plugin unreliable and unsuitable for most 100Mb (or faster) interfaces, where bursts are expected to exceed 50Mbps.  This means that this plugin is usuitable for most 32 bit production environments. To avoid this problem, use the ip_ plugin instead.  There should be no problems on 64 bit systems running 64 bit kernels."
	echo 'down.label received'
        echo 'down.type COUNTER'
        echo 'down.graph no'
        echo 'down.cdef down,8,*'
        echo 'up.label bps'
	echo 'up.type COUNTER'
	echo 'up.negative down'
	echo 'up.cdef up,8,*'
	print_warning down
	print_warning up
	print_critical down
	print_critical up

	findspeed

	exit 0
	;;
esac

# Escape dots in the interface name (eg. vlans) before using it as a regex
awk -v interface="$INTERFACE" \
    'BEGIN { gsub(/\./, "\\.", interface) } \
    $1 ~ "^" interface ":" {
        split($0, a, /: */); $0 = a[2]; \
        print "down.value " $1 "\nup.value " $9 \
    }' \
    /proc/net/dev

